import axios from 'axios'
import { Message, MessageBox } from 'element-ui'
import store from '@/store'
import { UserModule } from '@/store/modules/user'
import router from '@/router'
import { overdueLogin } from '@/api/login'
import { route_origins } from '@/api/routes'
// import { getToken } from '@/utils/auth'

/**
 *
 * @fileOverview [respone拦截器]
 * @const
 * @param {Number} [resultCode === -1]              [常用接口服务错误，个别业务-1后要求登出，之后建议服务端统一优化容错接口]
 * @param {Number} [resultCode === 204]             [约定为接口正常无数据的情况]
 * @param {Number} [resultCode === -100]            [登录失效或出错]
 * @param {Number} [resultCode === 205]             [无权限]
 * @param {Number} [resultCode === 206]             [IP白名单：访问受限]
 * @param {Binary} [N/A]                            [无状态码，交给业务端处理]
 * @param {Number} [resultCode !== (-100|-1|200)]   [返回res原对象交给具体业务内自定义处理（包括204）]
 *
 */

let isValidLogin = false
let isValidLogin100 = false
let isAborted = false
let isAuthAlerted = false
const closeReminder403 = true;
(window as any).loginErrStatus = false

const msgPopUp = (response: any, _custom: any) => {
    // this.$confirm(`${response.resultMsg}或登录过期, 请重新登录！`, response.resultMsg, {
    //     cancelButtonText: '取消',
    let _c = 0
    const _v = setInterval(t => {
        _c += 100
        // const errMsg = document.querySelectorAll('.el-message--error') as NodeListOf<HTMLElement>
        const errMsg: NodeListOf<Element> = document.querySelectorAll('.el-message--error')
        const buttons = <HTMLElement>document.querySelector('.el-message-box__btns')
        const buttons_subButtons: NodeListOf<Element> = buttons && buttons.querySelectorAll('button')
        // errMsg && errMsg.forEach((m: any, i: number) => {
        //     <HTMLElement>m.style.display = 'none';
        // })
        for (let i = 0; i < errMsg.length; i++) {
            const xDom = <HTMLElement>errMsg[i]
            xDom.style.display = 'none'
        }
        buttons && buttons_subButtons.forEach((m: any, i: number) => {
            if (i > 1) {
                buttons.removeChild(m)
            }
        })
        if (_c % 1000 === 0) {
            clearInterval(_v)
            _c = 0
        }
    }, 100)
    if (isValidLogin100) return
    const strInvalidNeg100 = response.resultMsg || '登录失效'
    response.resultMsg = response.resultCode === -100 ? strInvalidNeg100 : response.resultMsg
    const domLoginErr = <HTMLElement>document.querySelector('.err-tip') || {
        style: {}
    }
    if (response.resultCode > 100000) {
        (window as any).loginErrStatus = true
        console.warn('Login name, password, valiCode Error :', response)
        // console.log(document.querySelectorAll('.el-form-item__content')[2])
        domLoginErr.innerHTML = response.resultMsg
        domLoginErr.style.display = 'block'
        return
    }
    domLoginErr.style.display = 'none'
    setTimeout(() => {
        const customMsg = _custom || {}
        const _resultMsg = /http/img.test(response.resultMsg) ? '登录失效，请重新登录！' : response.resultMsg
        // const _msg = customMsg.msg || `${_resultMsg}或登录过期, 请重新登录！`
        const _msg = customMsg.msg || _resultMsg || '登录过期, 请重新登录！'
        const _title = customMsg.title || '提示'
        MessageBox.alert(_msg, _title, {
            confirmButtonText: '确定',
            type: 'warning',
            center: true
        }).then(() => {
            store.dispatch('LogOut').then(() => {
                console.warn('Logout')
                isValidLogin100 = false
                router.push({
                    // path: router.options.routes[0].path
                    path: '/'
                })
            })
        }).catch(() => {})
    }, 500)
    isValidLogin100 = true
}

const isAuthUserHandler = (response: any) => {
    console.warn('isAuthAlerted:', isAuthAlerted)
    if (closeReminder403 || isAuthAlerted) return
    MessageBox.alert(response.resultMsg || `当前用户没有权限, 请重新登录！`, '权限问题', {
        confirmButtonText: '确定',
        type: 'warning',
        center: true
    }).then(() => {
        store.dispatch('LogOut').then(() => {
            console.warn('Logout')
            router.push({
                // path: router.options.routes[0].path
                path: '/'
            })
        })
    }).catch(() => {})
    isAuthAlerted = true
}

const service = axios.create({
    baseURL: process.env.BASE_API,
    timeout: 15000
})
const servAny = (service as any)
servAny.defaults.withCredentials = true
servAny.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
servAny['_origin'] = { transformRequest: servAny.defaults.transformRequest }
servAny.defaults.transformRequest = [(data: any) => {
    let ret = ''
    for (const it in data) {
        ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'
    }
    return ret
}]

/**
 * [筛选过滤器：默认会过滤值为空字符的key字段]
 * @param  {Object} postData              [原始请求参数]
 * @param  {Array}  postData.erasedValues [自定义过滤的请求参数列表]
 * @param  {Array}  postData.keepValues   [自定义保留的请求参数列表]
 * @return {Object}                       [过滤后请求参数]
 */
servAny['filterPostData'] = (postData: any) => {
    let posts = {}
    postData.erasedValues = postData.erasedValues || []
    let erasedArr = [...postData.erasedValues, ...['', false, null, undefined, 'undefined']]
    for (const m in postData) {
        // if (postData[m] || postData[m] === 0) {
        if (erasedArr && erasedArr.includes(postData[m])) {
            continue
        }
        (posts as any)[m] = postData[m]
    }
    for (const n in postData) {
        if (postData.keepValues && postData.keepValues.includes(postData[n])) {
            (posts as any)[n] = postData[n]
        }
    }
    delete (posts as any).erasedValues
    delete (posts as any).keepValues
    return posts
}

servAny['ObjectToURIEncode'] = (params: any) => {
    // let urlparam:Array<string> = new Array<string>()
    // let array2:number[] = []
    let urlparam = []
    // Object.keys(params).forEach((m: any, i: number) => {
    //     urlparam += encodeURIComponent(m) + '=' + encodeURIComponent(Object.values(params)[i]) + '&'
    // })
    for (let ev in params) {
        urlparam.push(ev + '=' + params[ev])
    }
    return encodeURIComponent(urlparam.join('&'))
}

/**
 * [request拦截器]
 * @param  {Object} config [http header]
 * @return {Object}        [config]
 */
service.interceptors.request.use((config: any) => {
    // mock local
    if (location.port && config && config.url.match(new RegExp('/static/data/'))) {
        config.withCredentials = false
        config.method = 'get'
        config.url = location.origin + config.url + '.json?ajax'
        return config
    }
    // mock yapi
    if (config && config.url.match(/http\:\/\/yapi/img)) {
        config.withCredentials = false
    }
    // default
    config.url += '?ajax'
    return config
}, (error: any) => {
    console.log(error) // for debug
    Promise.reject(error)
})

/**
 * [response拦截器]
 * @param  {Object} response    [http response]
 * @return {Object} Promise     [Promise.then]
 * @throws {Object} Promise     [Promise.reject]
 */
service.interceptors.response.use((response: any) => {
        const res = response.data
        // service response
        /* if (response.status === 403) {
            isAuthUserHandler(response)
            return
        }*/
        if (res.resultCode) {
            (window as any).loginErrStatus = false
            if (res.resultCode > 100000) {
                if (res.resultCode > 200000) {
                    return res
                }
                isAborted = true
                const showPwdImg = <HTMLImageElement>document.querySelector('.show-pwd img') || {}
                showPwdImg.src = route_origins + 'jcaptcha?' + Date.now()
                return msgPopUp(res, null)
            }
            if (res.resultCode === 200 || res.resultCode === -1) {
                if (isAborted && res.resultCode === -1) return
                isAborted = false
                if (res.resultCode === -1 && res.resultCode !== -100 /* !/登录/img.test(res.resultMsg) && !isValidLogin*/) {
                    overdueLogin({}).then((response: any) => {
                        console.warn('overdueLogin:', response)
                        if (response && response['resultCode'] === -100 && !isValidLogin) {
                            isValidLogin = true
                            // isValidLogin100 = true
                            msgPopUp(response, null)
                        } else {
                            isValidLogin = false
                        }
                    }).catch((err: any) => {
                        Message({
                            message: err && err.resultMsg || '验证登录系统错误！',
                            type: 'error',
                            duration: 3000
                        })
                    })
                }
                if (res.resultCode === -1) {
                    Message({
                        message: res.resultMsg || '接口服务错误！',
                        type: 'error',
                        duration: 3 * 1000
                    })
                    return
                }
                (res.module instanceof Object) && (res.module.resultCode = res.resultCode)
                return res.module || res.data || res
            }
            isAborted = false
            console.error('resultCode!=(200|-1|>100000):', res)
            // invalidCodes约定为接口异常的情况：统一弹错误提示，并登出
            const invalidCodes = [-100,
                // 205,
                206
            ]
            if (invalidCodes.includes(res.resultCode)) {
                const myMsg = res.resultCode === -100 ? null : {
                    msg: res.resultMsg
                }
                return msgPopUp(res, myMsg)
            }
            // 正常结果代码（200等），返回res原对象交给具体业务内自定义处理
            return res
        }

        if (res.resultMsg) {
            Message({
                message: res.resultMsg,
                type: 'error',
                duration: 3 * 1000
            }
)        }

        // 50008:非法的token; 50012:其他客户端登录了;  50014:Token 过期了;
        if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
            MessageBox.confirm('你已被登出，可以取消继续留在该页面，或者重新登录', '确定登出', {
                confirmButtonText: '重新登录',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                store.dispatch('FedLogOut').then(() => {
                    // location.reload() // 为了重新实例化vue-router对象 避免bug
                })
            })
        }
        return Promise.reject('error')
    },
    (error: any) => {
        console.log('err' + error) // for debug
        // browser response
        if (error && error.response && error.response.status === 403) {
            isAuthUserHandler(error.response)
            return
        }
        if (error.resultMsg) {
            Message({
                message: error.resultMsg,
                type: 'error',
                duration: 3 * 1000
            })
        }
        return Promise.reject(error)
    }
)

export default service
